package com.demo.webapp.action;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.demo.core.dao.base.support.PageSupport;
import com.demo.core.dao.base.support.SearchArgumentSupport;
import com.demo.core.dao.base.support.SearchResultSupport;
import com.demo.core.dao.base.support.SortAble;

/**
 * 可分页Action
 * ①、提供分页信息基础
 * ②、提供排序功能
 * 
 * @author ryuu.kk
 *
 */
public class PageAction extends BaseActionSupport implements PageSupport, SortAble {

	/**
	 * 版本序列化ID
	 */
	private static final long serialVersionUID = 1910860952340686316L;

	/**
	 * 分页参数名
	 */
	public static final String PAGE_PARAMS = "currentPage";
	
	/**
	 * 分页检索结果封装对象(Out对象)
	 */
	private SearchResultSupport<?> resultSupport;
	
	/**
	 * 分页检索条件封装对象(In对象)
	 */
	private SearchArgumentSupport argumentSupport;
	
	/**
	 * 当前页在总页数中的第几页
	 */
    private int currentPage = 1;
    
    /**
     * 总显示页数
     */
    private int totalPage = 0;
    
	/**
	 * 分页类型
	 * 存储分页类型
	 * 存储每页显示数据条数(rowSize)
	 */
	private Page page = Page.normal;
	
	/**
	 * 分页大小
	 * 与Page并列使用.
	 * pageSize的问题是允许用户自由指定分页长度,
	 * 可能造成恶意全数据检索。
	 */
	private int pageSize;
	
	/**
	 * 排序字段列表
	 */
	private List<Sort> sortList;
	
	/**
	 * 允许自动匹配 
	 */
	private boolean allowAutoMatch = true;
	
	/**
	 * 排序字段-表结构模型映射
	 */
	private Map<String, String> sortMapping;
	
	// -----------------------------------------------
	// 新增提供总结果条数方法 at 2013-02-04 by ryuu.kk
	/**
	 * 返回总条数
	 * @return 总条数
	 */
	public int getTotalResults() {
		int totalResult = 0;
		if (resultSupport != null) {
			totalResult = resultSupport.getTotalResults();
		}
		return totalResult;
	}
	// -----------------------------------------------
	
	/**
	 * OUT 返回显示的总页数
	 * 
	 * @return 总页数
	 */
	public int getTotalPage() {
		if (resultSupport == null) {
			//#webapp.result.support.not.found=ResultSupport not found from this application.
			log.warn(super.getText("webapp.result.support.not.found"));
			if (totalPage < 1) {
				totalPage = 1;
			}
			// 非分页接口实现分页时,由应用自行处理总页数
			if (currentPage > totalPage) {
				totalPage = currentPage;
			}
			return totalPage;
		}
		//计算总页数
		int resultCount = resultSupport.getTotalResults();
		int pageSize = page.size();
		if (resultCount % pageSize == 0) {
			totalPage = resultCount / pageSize;
		} else {
			totalPage = resultCount / pageSize + 1;
		}
		return totalPage;
	}
	
	/**
	 * IN 设置总页数
	 * 该方法为非SearchResultSupport接口实现分页提供方便。
	 * @param total 总页数
	 */
	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	/**
	 * OUT 返回当前第{n}页
	 * @return int 返回当前第{n}页
	 */
    public int getCurrentPage() {
    	int total = getTotalPage();
    	return currentPage > 0 ? (currentPage > total ? total : currentPage) : 1;
    }

    /**
     * IN 设置当前第{n}页
     * @param currentPage 当前第{n}页
     */
	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}
	
	/**
	 * IN 设置分页类型
	 * 由页面参数设置
	 * 创建选择分页类型模型,保存分页的每页最大显示条数
	 * 
	 * @param pageType 分页类型
	 */
	public void setPageType(int pageType) {
		switch (pageType) {
		case 1 << 0:
			page = Page.normal;
			break;
		case 1 << 1:
			page = Page.short_20;
			break;
		case 1 << 2:
			page = Page.short_50;
			break;
		case 1 << 3:
			page = Page.large_100;
			break;
		default:
			page = Page.normal;
		}
	}
	
	/**
	 * OUT 返回页面分页的每页数据条数
	 * 
	 * @return 每页数据条数
	 */
	@Override
	public int getPageSize() {
		if (this.pageSize > 0 && this.pageSize <= Page.large_100.size()) {
			return this.pageSize;
		}
		return page.size();
	}
	
	public void setPageSize(int size) {
		this.pageSize = size;
	}
	
	/**
	 * OUT 返回分页的分页URL地址
	 * @param index 第index页
	 * @return String 分页地址
	 */
	public String getPageUrl(int index) {
		// 参数中存在分页参数.
		boolean hasPage  = false;
		String pageUrl = "";
		// 取得当前地址
		String url = this.getRequest().getRequestURI();
		// 取得参数字符串
		String queryString = this.getRequest().getQueryString();
		Enumeration<?> e = this.getRequest().getParameterNames();
		while(e.hasMoreElements()) {
			String key = (String) e.nextElement();
			if (PAGE_PARAMS.equals(key)) {
				hasPage = true;
				break;
			}
		}
		
		// 存在分页参数
		if (hasPage) {
			// 将分页参数替换掉
			int begin = queryString.indexOf(PAGE_PARAMS);
			int end = queryString.indexOf("&", begin);
			// 替换掉分页参数
			if (end > 0) {
				// 分页参数在中间
				queryString = queryString.replace(queryString.substring(begin, end + 1), "");
			} else {
				// 分页参数在最后
				queryString = queryString.replace(queryString.substring(begin - 1), "");
			}
		}
		
		if (StringUtils.isNotBlank(queryString)) {
			url += "?" + queryString;
		}
		if (url.indexOf("?") > 0) {
			pageUrl = url + "&" + PAGE_PARAMS + "=" + index;
		} else {
			pageUrl = url + "?" + PAGE_PARAMS + "=" + index;
		}
		return getResponse().encodeURL(pageUrl);
	}

	/**
	 * 创建分页参数
	 * 该封装参数对象
	 * 
	 * @return 检索参数对象
	 */
	@Override
	public SearchArgumentSupport getArgumentSupport() {
		//每页显示的条数
		int intPageSize = getPageSize();
		if (currentPage < 1) currentPage = 1;
		//计算查询数据在整个数据集的位置= 每页数据条数 * (当前页 - 1) + 1
		argumentSupport = new SearchArgumentSupport(intPageSize * (this.currentPage - 1), intPageSize); 
		// 进行排序字段处理
		buildOrderArgs(argumentSupport);
		
		return argumentSupport;
	}
	
	/**
	 * 设置检索结果对象
	 * 
	 * @param resultSupport 检索对象集封装对象
	 */
	@Override
	public void setResultSupport(SearchResultSupport<?> resultSupport) {
		this.resultSupport = resultSupport;
	}

	/**
	 * 当前页是否是第一页
	 * @return boolean
	 */
	@Override
	public boolean isFirst() {
		return currentPage == 1;
	}

	/**
	 * 当前页是否是最后一页
	 * @return boolean
	 */
	@Override
	public boolean isLast() {
		return this.getTotalPage() == 0 ? true : currentPage == this.getTotalPage();
	}

	@Override
	public void setSortList(List<Sort> sortList) {
		this.sortList = sortList;
	}

	public List<Sort> getSortList() {
		return sortList;
	}

	@Override
	public Map<String, String> getSortMapping() {
		return this.sortMapping;
	}

	@Override
	public void allowAutoMatch(boolean allow) {
		this.allowAutoMatch = allow;
	}
	
	/**
	 * 编辑排序参数
	 * @param argumentSupport 分页/排序参数模型
	 */
	private void buildOrderArgs(SearchArgumentSupport argumentSupport) {
		if (sortList != null && sortList.size() > 0) {
			List<String> orderList = new ArrayList<String>();
			for (Sort sort : sortList) {
				if (sort.getType() > 0) {
					// 需要增加自动排序功能
					String name = sort.getName();
					String key = "";
					if (sortMapping != null) {
						 key = sortMapping.get(name);
					}
					// 不存在判断
					if (StringUtils.isBlank(key) 
							&& StringUtils.isNotBlank(name) 
							&& allowAutoMatch) {
						// 映射中没有该排序字段,并且允许自动匹配: userName -> USER_NAME
						// 存在一个问题:命名中不得有数字
						String[] tmp = name.split("(?<=[a-z])(?=[A-Z])");
						for (String s : tmp) {
							key += s.toUpperCase().trim() + "_";
						}
						// 去掉最后"_"
						key = key.substring(0, key.length() - 1);
						
					}
					// 1:升序,2降序
					String type = sort.getType() %2 == 0? "DESC": "ASC";
					if (StringUtils.isNotBlank(key)) {
						orderList.add( key + " " +type);
					}
				}
			}
			// 将排序字段加入到分页模型中
			argumentSupport.setOrders(orderList.toArray(new String[]{}));
		}
	}
	
	public static void main(String[] args) {
		
		String[] tmp = "helloWorldLog4j".split("(?<=[a-z])(?=[A-Z])");
		for (String s : tmp) {
			System.out.print(s + "-");
		}
		
		// 存在分页参数
		String pageParams = PAGE_PARAMS;
		String queryString = "aaa=bbb&ccc=ddd&"+PAGE_PARAMS+ "=123&abdas=12&abdas=12&abdas=12";
		System.out.println(" ");
		System.out.println(" " + queryString);
		if (pageParams != null && pageParams.length() > 0) {
			// 将分页参数替换掉
			int begin = queryString.indexOf(PAGE_PARAMS);
			int end = queryString.indexOf("&", begin);
			// 替换掉分页参数
			if (end > 0) {
				// 分页参数在中间
				queryString = queryString.replace(queryString.substring(begin, end + 1), "");
			} else {
				// 分页参数在最后
				queryString = queryString.replace(queryString.substring(begin - 1), "");
			}
		} 
		System.out.println("\n ----------------------------");
		
		
		System.out.println(queryString);
		
	}
}
